vimfandomcom-20200223-history
Search across multiple lines
Vim can search for text that spans multiple lines. For example, the search /hello\_sworld finds "hello world" in a single line, and also finds "hello" ending one line, with "world" starting the next line. In a search, \s finds space or tab, while \_s finds newline or space or tab: an underscore adds a newline to any character class. This tip shows how to search over multiple lines, and presents a useful command so entering :S hello world finds "hello" followed by "world" separated by spaces or tabs or newlines, and :S! hello world allows any non-word characters, including newlines, between the words. Patterns including end-of-line The search /^abcd finds abcd at the beginning of a line, and /abcd$ finds abcd at the end of a line. However, in /abcd^efgh and /abcd$efgh the ^ and $ are just ordinary characters with no special meaning. By contrast, each of the following has a special meaning anywhere in a search pattern. Example searches: ;/abcd\n*efgh :Finds abcd followed by zero or more newlines then efgh. :Finds abcdefgh or abcd followed by blank lines and efgh. :The blank lines have to be empty (no space or tab characters). ;/abcd\_s*efgh :Finds abcd followed by any whitespace or newlines then efgh. :Finds abcdefgh or abcd followed by blank lines and efgh. :The blank lines can contain any number of space or tab characters. :There may be whitespace after abcd or before efgh. ;/abcd\_$\_s*efgh :Finds abcd at end-of-line followed by any whitespace or newlines then efgh. :There must be no characters (other than a newline) following abcd. :There can be any number of space, tab or newline characters before efgh. ;/abcd\_s*\_^efgh :Finds abcd followed by any whitespace or newlines then efgh where efgh begins a line. :There must be no characters (other than a newline) before efgh. :There can be any number of space, tab or newline characters after abcd. ;/abcd\_$efgh :Finds nothing because \_$ is "zero width" so the search is looking for abcdefgh where abcd is also at end-of-line (which cannot occur). ;/abcd\_^efgh :Finds nothing because \_^ is "zero width" so the search is looking for abcdefgh where efgh is also at beginning-of-line (which cannot occur). ;/abcd\_.\{-}efgh :Finds abcd followed by any characters or newlines (as few as possible) then efgh. :Finds abcdefgh or abcd followed by any characters then efgh. ;/abcd\(\_s.*\)\{0,18\}\_sefgh :Finds a block of 0 to 18 lines enclosed by abcd and efgh. :limiting the number of lines is important, replacing this by a star will cause vim to consume 100% CPU. Searching for multiline HTML comments It is common for comments in HTML documents to span several lines: The following search finds any HTML comment: / The atom \_. finds any character including end-of-line. The multi \{-} matches as few as possible (stopping at the first "-->"; the multi * is too greedy and would stop at the last occurrence). Syntax highlighting may be not be accurate, particularly with long comments. The following command will improve the accuracy when jumping in the file, but may be slower ( ): :syntax sync fromstart Searching over multiple lines A pattern can find any specified characters, for example, aeiou matches 'a' or 'e' or 'i' or 'o' or 'u'. In addition, Vim defines several character classes. For example, \a is A-Za-z (matches any alphabetic character), and \A is ^A-Za-z (opposite of \a; matches any non-alphabetic character). An underscore can be used to extend a character class to include a newline (end of line). For example, searching for \_aeiou finds a newline or a vowel, so \_aeiou\+ matches any sequence of vowels, even a sequence spanning multiple lines. Similarly, \_a\+ matches any sequence of alphabetic characters, even when spanning multiple lines. The following search pattern finds "hello world" where any non-alphabetic characters separate the words: hello\_^a-zA-Z*world The above pattern (which is equivalent to hello\_A*world) matches "helloworld", and "hello? ... world", and similar strings, even if "hello" is on one line and "world" is on a following line. Searching over multiple lines with a user command The script below defines the command :S that will search for a phrase, even when the words are on different lines. Examples: ;:S hello world :Searches for "hello" followed by "world", separated by whitespace including newlines. ;:S! hello world :Searches for "hello" followed by "world", separated by any non-word characters (whitespace, newlines, punctuation). :Finds, for example, "hello, world" and "hello+world" and "hello ... world". The words can be on different lines. After entering the command, press n or N to search for the next or previous occurrence. Put the following in your vimrc (or in file searchmultiline.vim in your plugin directory): " Search for the ... arguments separated with whitespace (if no '!'), " or with non-word characters (if '!' added to command). function! SearchMultiLine(bang, ...) if a:0 > 0 let sep = (a:bang) ? '\_W\+' : '\_s\+' let @/ = join(a:000, sep) endif endfunction command! -bang -nargs=* -complete=tag S call SearchMultiLine(0, )|normal! // See also *Searching how to search *Search patterns regex information and examples *Search for visually selected text search for selected text; finds targets on multiple lines References * Comments